package com.h2cloud.ThreadLocalTest;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Package: com.h2cloud.ThreadLocalTest
 * @ClassName: transmittableTest
 * @Author: h2cloud
 * @CreateTime: 2024/3/7 12:18 上午
 * @Description:
 */
public class transmittableTest {

	// 需要注意的是，使用TTL的时候，要想传递的值不出问题，线程池必须得用TTL加一层代理（下面会讲这样做的目的）
	private static ExecutorService executorService = Executors.newFixedThreadPool(2);

	private static ThreadLocal tl = new TransmittableThreadLocal<>(); //这里采用TTL的实现

	public static void main(String[] args) {

		new Thread(() -> {

			String mainThreadName = "main_01";
			tl.set(1);

			executorService.execute(() -> {
				sleep(3L);
				System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});

			executorService.execute(() -> {
				sleep(3L);
				System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});

			executorService.execute(() -> {
				sleep(3L);
				System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});
			tl.set(2); // 等上面的线程池第一次启用完了，父线程再给自己赋值
			sleep(3L); //确保上面的会在tl.set执行之前执行
			tl.set(2); // 等上面的线程池第一次启用完了，父线程再给自己赋值

			executorService.execute(() -> {
				sleep(1L);
				System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});

			executorService.execute(() -> {
				sleep(1L);
				System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});

			System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
			sleep(3L); //确保上面的会在tl.set执行之前执行
			executorService.execute(() -> {
				sleep(1L);
				tl.set(3);
				System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
			});

			System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));

		}).start();


		// new Thread(() -> {
		//
		// 	String mainThreadName = "main_02";
		//
		// 	tl.set(3);
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	sleep(1L); //确保上面的会在tl.set执行之前执行
		// 	tl.set(4); // 等上面的线程池第一次启用完了，父线程再给自己赋值
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	executorService.execute(() -> {
		// 		sleep(1L);
		// 		System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
		// 	});
		//
		// 	System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
		//
		// }).start();

	}

	private static void sleep(long time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
